package homework6;

import java.util.Scanner;


/**
 * GetX()
 * 
 * @data 2013.7.23
 * @declaration Calculate the ~integrate
 * @author 121250125
 * 
 * Listing Contents:
 * @method: main(String[] args)
 *  		,xPredict()
 * 			,pCalculate(double x)
 * 			,fCalculate(double x)
 * 			,gammaCalculate(double x)
 * 			,sumFCalculate(double x, int beginTag)
 */


public class GetX {
	public static final int NUM_SEG = 100;
	public static final int E = 5;
	public static double W = 0;
	public static int dof = 0;
	public static double x = 1.0;
	public static double p;
	public static double d = 0.5;
	
	
	
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("Input the p: ");
		p = Double.valueOf(sc.nextLine());
		
		System.out.print("Input the dof(degrees of freedom): ");
		dof = Integer.valueOf(sc.nextLine());
		x = xPredict();
		System.out.println(String.format(
				("The expected value is: %." + E + "f"), x));
		
	}// end
	
	
	/**
	 * xPredict()
	 * 
	 * @declaration: Calculate the x
	 * @param x
	 * @return p
	 */
	public static double xPredict() {
		boolean restate = false;//false is p>P(X)
		if(p != pCalculate(x)) {
			if(p > pCalculate(x)) {
				x = x + d;
				restate = false;
			}
			else {
				x = x - d;
				restate = true;
			}
 
			while(pCalculate(x) != p) {
				if(p > pCalculate(x)) {
					if(restate == false) {
						x = x + d; 
					}
					else {
						d = d / 2;
						x = x + d; 
					}
					restate = false;
				}
				else if(p < pCalculate(x)) {
					if(restate) {
						d = d / 2;
						x = x - d;
					}
					else {
						x = x - d;
					}
					restate = true;
				}		
			}
		}
		return x;
	}// end
	
	
	/**
	 * pCalculate(double x)
	 * 
	 * @declaration: Calculate the p
	 * @param x
	 * @return p
	 */
	public static double pCalculate(double x) {
		W = x / NUM_SEG;
		double oddCal = 4 * sumFCalculate(x, 1);
		double evenCal = 2 * sumFCalculate(x, 2);
		double result = (W / 3.0) * (fCalculate(0) + oddCal + evenCal + fCalculate(x));
		return result;
		
		
	}// end

	/**
	 * fCalculate(double x)
	 * 
	 * @declaration: Calculate the F
	 * @param x
	 * @return ans
	 */
	public static double fCalculate(double x) {
		double gamma1 = gammaCalculate((dof + 1) / 2.0);
		double gamma2 = gammaCalculate(dof / 2.0);
		return (gamma1 / (Math.sqrt(dof * Math.PI) * gamma2))
				* Math.pow((1 + x * x / dof), -((dof + 1) / 2.0));
		
	}// end

	/**
	 * gammaCalculate(double x)
	 * 
	 * @declaration: Calculate the gamma()
	 * @param x
	 * @return ans
	 */
	public static double gammaCalculate(double x) {
		if (x == 1.0) {
			return 1;
		} else if (x == 0.5) {
			return Math.sqrt(Math.PI);
		} else {
			return (x - 1) * gammaCalculate(x - 1);
		}
		
	}// end

	/**
	 * sumFCalculate(double x, int beginTag)
	 * 
	 * @declaration: Calculate sum of F
	 * @param x
	 *            ,beginTag
	 * @return ans
	 */
	public static double sumFCalculate(double x, int beginTag) {
		double ans = 0;
		for (int i = beginTag; i < NUM_SEG; i += 2) {
			ans += fCalculate(i * W);
		}
		return ans;
		
	}// end

}
